Google C++ Code Style Notes

Google C++ Code Style Notes

头文件

  • 为了防止多重包含,所以的头文件加上 #define 保护,例如项目 foo/src/bar/baz.h 按如下方式保护:

    #ifndef FOO_BAR_BAZ_H_
    #define FOO_BAR_BAZ_H_
    ...
    #endif // FOO_BAR_BAZ_H_
    
  • 使用前置声明(forward declarations)减少 .h 文件中的 #include 数量

  • 函数小于等于10行定义为 inline function 且放在头文件中,循环,递归,switch 不应该包含在内联函数中

  • 函数参数输入在前,输出在后

  • 头文件包含顺序:C库,C++库,其他库,项目内库

作用域

  • .cc 中的不具名命名空间可避免命名冲突、限定作用域,避免直接使用 using 提示符污
    染命名空间;
  • 尽量不用全局函数和全局变量,考虑作用域和命名空间限制,尽量单独形成编译单元;
  • 将函数变量尽可能置于最小作用域内,在声明变量时将其初始化,离第一次使用越近越好;
  • 嵌套类符合局部使用原则,只是不能在其他头文件中前置声明,尽量不要 public
    public;

  • 不要在构造函数中实现复杂的初始化,通过Init()方法实现;只有一个参数的构造函数用 explicit 关键字修饰,避免不必要的隐式转换;大部分类并不需要可拷贝,可在 private 声明空的拷贝构造函数和赋值操作以避免编译器自动在 public 生成,赋值操作注意检测自赋值的情况

  • 仅使用数据时使用 struct,其他使用 class

  • 只使用公共继承,B is-a A 的情况下才令B是A的子类,has-a 的情况下使用组合;成员函数含有虚函数则析构函数也应该为虚;仅在子类访问的成员函数应为 protect,数据成员始终为 private;重新定义一个继承来的虛函数时,子类中要明确声明其为 virtual

  • 多重继承(略)

  • 存取函数一般内敛在头文件

  • 类中声明次序:public>protected>private

    1. typedefs and enums
    2. constants
    3. constructors
    4. destructor
    5. methods
    6. data
  • 短小精练的函数 is better, 长函数最好不要超过40行

其他 C++ 特性

  • 按引用传递的参数必须加上 const

  • 禁止使用缺省函数参数

  • 禁止使用变长数组和 alloca,使用安全的分配器,如 scoped_ptr/scoped_array

  • 不要使用c风格的类型转换,使用 static_cast<>()

  • 只在记录日志时使用流

  • 一般使用前置自增,效率更高,后置自增会对表达式的值i有一次拷贝

  • 尽可能多的使用 const:

    1. 如果函数不会修改传入的引用或指针类型的参数,这样的参数应该为 const;
    2. 尽可能将函数声明为 const, 访问函数应该总是 const, 其他函数如果不会修改任何数据成员也应该是const, 不要调用非 const 函数, 不要返回对数据成员的非 const 指针或引用;
    3. 如果数据成员在对象构造之后不再改变,可将其定义为 const;
  • 要使用精确位数的整型可使用 stdint.h 头文件中的 int16_t 等;不要使用无符号整型,使用断言 assert 声明变量为非负数

  • 整数用 0, 实数用 0.0, 指针用 NULL, 字符(串)用’\0’。

  • 尽可能用 sizeof(varname)代替 sizeof(type)。

命名约定

  • 不要随意缩写,除函数名可适当为动词,其他命名尽量使用清晰易懂的名词

  • 类型命名(class, struct, typedef, enum),普通函数,常量(以k开头)每个单词以大写开头不包含下划线

  • 宏、枚举值等全部使用大写加下划线

  • 变量,文件名,命名空间,存取函数等使用小写字母加下划线,类成员变量以下划线结束,全局变量以g_开头

注释

  • 文件注释:版权、许可版本、作者、文件内容
  • 类注释:每个类的定义要增加对其功能和用法的注释
  • 函数注释:
    1. 声明处:inputs(输入)及 outputs(输出);如果函数分配了空间,需要由调用者释放;参数是否可以为 NULL;是否存在函数使用的性能隐忧(performance implications)
    2. 定义处:函数功能和实现要点,如使用的漂亮代码、实现的简要步骤、
      如此实现的理由、为什么前半部分要加锁而后半部分不需要。
  • TODO注释:// TODO(kl@gmail.com): Use a “*” here for concatenation operator.
    // TODO(Zeke) change this to use relations.

格式

  • 只用空格,不要使用 tab,设定编译器将 tab 转为空格
  • 预处理指令和命名空间不使用额外缩进
  • 水平/垂直留白不要滥用